package com.spddr.pmos.oauth2;

import javax.ws.rs.CookieParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.NewCookie;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.core.UriBuilder;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.cxf.jaxrs.ext.MessageContext;
import org.apache.cxf.jaxrs.utils.ExceptionUtils;
import org.apache.cxf.jaxrs.utils.JAXRSUtils;
import org.apache.cxf.rs.security.oauth2.common.AccessToken;
import org.apache.cxf.rs.security.oauth2.common.Client;
import org.apache.cxf.rs.security.oauth2.common.OAuthError;
import org.apache.cxf.rs.security.oauth2.common.ServerAccessToken;
import org.apache.cxf.rs.security.oauth2.tokens.bearer.BearerAccessToken;
import org.apache.cxf.rs.security.oauth2.utils.OAuthConstants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;

import com.spddr.pmos.jpa.User;
import com.spddr.pmos.repos.UserRepos;

import cn.seqdata.cxf.utils.ViolationUtils;

@Service
public class JaxrsOauthSignImpl implements OauthSign {
	@Autowired
	private ApplicationContext ctx;

	@Context
	protected MessageContext mc;

	@Autowired
	protected Oauth2DataProviderImpl dataProvider;

	@Autowired
	protected UserRepos userRepos;

	@CookieParam(OAuthConstants.ACCESS_TOKEN)
	protected String token;

	@Override
	public Response signIn(String username, String password, String redirect) {
		Client client = dataProvider.getClient(username);
		if (null == client) {
			ViolationUtils.throwViolationException(null, "username", username, "无效的用户名");
		}

		if (!StringUtils.equals(client.getClientSecret(), password)) {
			ViolationUtils.throwViolationException(null, "password", "******", "密码错误");
		}

		ServerAccessToken serverToken = dataProvider.getAccessToken(client.getClientId());
		if (null == serverToken) {
			serverToken = new BearerAccessToken(client, 6 * 3600L);
			dataProvider.saveAccessToken(serverToken);
		}

		ResponseBuilder rb;
		if (StringUtils.isBlank(redirect)) {
			token = serverToken.getTokenKey();
			rb = Response.ok(info());
		} else {
			rb = Response.temporaryRedirect(UriBuilder.fromUri(redirect)
					.build());
		}
		setAuthorizationHeader(rb, serverToken);
		return rb.build();
	}

	@Override
	public Response signOut() {
		ServerAccessToken sat = dataProvider.getAccessToken(token);
		if (null != sat) {
			dataProvider.removeAccessToken(sat);
			dataProvider.removeClient(sat.getClient()
					.getClientId());
		}

		ResponseBuilder rb = Response.status(Status.UNAUTHORIZED);
		removeAuthorizationHeader(rb);
		return rb.build();
	}

	@Override
	public Response changePswd(String oldpswd, String newpswd) {
		ServerAccessToken accessToken = dataProvider.getAccessToken(token);

		Client client = accessToken.getClient();
		if (!client.getClientSecret()
				.equalsIgnoreCase(oldpswd)) {
			ViolationUtils.throwViolationException(null, "oldpswd", oldpswd, "输入的旧密码不匹配！");
		}

		long userId = NumberUtils.toLong(client.getSubject()
				.getId());
		userRepos.updatePassword(userId, newpswd);

		User e = userRepos.findOne(userId);
		// dataProvider.removeClient(e.getUsername);

		ResponseBuilder rb = Response.ok("密码修改成功，请重新登录。");
		removeAuthorizationHeader(rb);
		return rb.build();
	}

	@Override
	public SubjectInfo info() {
		// if (StringUtils.isBlank(token))
		// return null;

		// try {
		SubjectInfo subject = new SubjectInfo();
		//
		// ServerAccessToken accessToken = dataProvider.getAccessToken(token);
		// Client client = accessToken.getClient();
		// UserSubject userSubject = client.getSubject();
		// Long userId = NumberUtils.toLong(userSubject.getId());
		// User user = userRepos.findOne(userId);
		//
		// subject.id = userId;
		// subject.name = user.getName();
		subject.name = "演示用户";
		// subject.username = user.getUsername();
		// subject.org = user.getRegion().getId();

		return subject;
		// } catch (RuntimeException ex) {
		// Response r = Response.status(Status.UNAUTHORIZED).build();
		// throw ExceptionUtils.toNotAuthorizedException(ex, r);
		// }
	}

	protected void setAuthorizationHeader(ResponseBuilder rb, AccessToken accessToken) {
		// 设置 Authorization 头，客户端应用应该获取此头并在每次请求时一并提交
		rb.header(OAuthConstants.AUTHORIZATION_SCHEME_TYPE, accessToken.getTokenType());
		rb.header(OAuthConstants.AUTHORIZATION_SCHEME_DATA, accessToken.getTokenKey());

		// 设置access_token={}的cookie，作用范围/，浏览器关闭后失效
		NewCookie cookie = new NewCookie(OAuthConstants.ACCESS_TOKEN, accessToken.getTokenKey(), "/rest", null, null,
				NewCookie.DEFAULT_MAX_AGE, false);
		rb.cookie(cookie);
	}

	protected void removeAuthorizationHeader(ResponseBuilder rb) {
		NewCookie cookie = new NewCookie(OAuthConstants.ACCESS_TOKEN, null, "/rest", null, null, 0, false);
		rb.cookie(cookie);
	}

	protected WebApplicationException toInvalidRequestException(String errorDescription) {
		ResponseBuilder rb = JAXRSUtils.toResponseBuilder(Status.BAD_REQUEST);
		OAuthError error = new OAuthError(OAuthConstants.INVALID_REQUEST, errorDescription);
		return ExceptionUtils.toBadRequestException(null, rb.entity(error)
				.build());
	}
}
